/**
 * @file http_client.cpp
 * @brief HTTP客户端实现
 * @author 29108
 * @date 2025/7/25
 */

#include "common/http/http_client.h"
#include <sstream>
#include <regex>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>

namespace common {
namespace http {

    HttpClient::HttpClient() {
        // 设置默认请求头
        default_headers_["User-Agent"] = "HttpClient/1.0";
        default_headers_["Connection"] = "close";
    }

    HttpClient::~HttpClient() = default;

    HttpClientResponse HttpClient::get(const std::string& url, int timeout_ms) {
        return sendRequest("GET", url, "", {}, timeout_ms);
    }

    HttpClientResponse HttpClient::post(const std::string& url, 
                                      const std::string& body,
                                      const std::unordered_map<std::string, std::string>& headers,
                                      int timeout_ms) {
        return sendRequest("POST", url, body, headers, timeout_ms);
    }

    HttpClientResponse HttpClient::put(const std::string& url,
                                     const std::string& body,
                                     const std::unordered_map<std::string, std::string>& headers,
                                     int timeout_ms) {
        return sendRequest("PUT", url, body, headers, timeout_ms);
    }

    HttpClientResponse HttpClient::del(const std::string& url, int timeout_ms) {
        return sendRequest("DELETE", url, "", {}, timeout_ms);
    }

    void HttpClient::setDefaultHeader(const std::string& key, const std::string& value) {
        default_headers_[key] = value;
    }

    void HttpClient::setDefaultTimeout(int timeout_ms) {
        default_timeout_ms_ = timeout_ms;
    }

    HttpClientResponse HttpClient::sendRequest(const std::string& method,
                                             const std::string& url,
                                             const std::string& body,
                                             const std::unordered_map<std::string, std::string>& headers,
                                             int timeout_ms) {
        HttpClientResponse response;
        
        try {
            // 解析URL
            std::string host, path;
            int port;
            if (!parseUrl(url, host, port, path)) {
                response.error_message = "Invalid URL: " + url;
                return response;
            }

            // 调试信息：记录解析结果
            LOG_DEBUG("HTTP客户端解析URL: " + url);
            LOG_DEBUG("  - Host: " + host);
            LOG_DEBUG("  - Port: " + std::to_string(port));
            LOG_DEBUG("  - Path: " + path);

            // 创建socket
            int sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd < 0) {
                response.error_message = "Failed to create socket";
                return response;
            }

            // 设置非阻塞模式
            int flags = fcntl(sockfd, F_GETFL, 0);
            fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

            // 解析主机名 - 优先使用IP地址避免DNS阻塞
            struct sockaddr_in serv_addr;
            memset(&serv_addr, 0, sizeof(serv_addr));
            serv_addr.sin_family = AF_INET;
            serv_addr.sin_port = htons(port);

            // 尝试直接解析IP地址
            if (inet_aton(host.c_str(), &serv_addr.sin_addr) == 0) {
                // 如果不是IP地址，则进行DNS解析
                struct hostent* server = gethostbyname(host.c_str());
                if (server == nullptr) {
                    close(sockfd);
                    response.error_message = "Failed to resolve hostname: " + host;
                    return response;
                }
                memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length);
            }

            // 连接服务器
            LOG_DEBUG("尝试连接到 " + host + ":" + std::to_string(port) + " (IP: " + inet_ntoa(serv_addr.sin_addr) + ")");

            int connect_result = connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
            if (connect_result < 0 && errno != EINPROGRESS) {
                close(sockfd);
                response.error_message = "Failed to connect to server " + host + ":" + std::to_string(port) +
                                       " (errno: " + std::to_string(errno) + ", " + strerror(errno) + ")";
                LOG_ERROR("连接失败: " + response.error_message);
                return response;
            }

            LOG_DEBUG("连接状态: " + std::string(connect_result == 0 ? "立即成功" : "等待完成"));

            // 等待连接完成
            if (connect_result < 0) {
                fd_set write_fds;
                FD_ZERO(&write_fds);
                FD_SET(sockfd, &write_fds);
                
                struct timeval timeout;
                timeout.tv_sec = timeout_ms / 1000;
                timeout.tv_usec = (timeout_ms % 1000) * 1000;
                
                int select_result = select(sockfd + 1, nullptr, &write_fds, nullptr, &timeout);
                if (select_result <= 0) {
                    close(sockfd);
                    response.error_message = "Connection timeout to " + host + ":" + std::to_string(port) +
                                           " after " + std::to_string(timeout_ms) + "ms";
                    return response;
                }
            }

            // 构建HTTP请求
            std::string request = buildHttpRequest(method, path, host, body, headers);
            
            // 发送请求
            LOG_DEBUG("发送HTTP请求到 " + host + ":" + std::to_string(port));
            LOG_DEBUG("请求内容: " + request.substr(0, 200) + (request.length() > 200 ? "..." : ""));

            ssize_t bytes_sent = send(sockfd, request.c_str(), request.length(), 0);
            if (bytes_sent < 0) {
                close(sockfd);
                response.error_message = "Failed to send request to " + host + ":" + std::to_string(port);
                return response;
            }

            LOG_DEBUG("成功发送 " + std::to_string(bytes_sent) + " 字节到 " + host + ":" + std::to_string(port));

            // 接收响应
            std::string response_data;
            char buffer[4096];
            
            fd_set read_fds;
            struct timeval recv_timeout;
            
            while (true) {
                FD_ZERO(&read_fds);
                FD_SET(sockfd, &read_fds);
                recv_timeout.tv_sec = timeout_ms / 1000;
                recv_timeout.tv_usec = (timeout_ms % 1000) * 1000;
                
                int select_result = select(sockfd + 1, &read_fds, nullptr, nullptr, &recv_timeout);
                if (select_result <= 0) {
                    break; // 超时或错误
                }
                
                ssize_t bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
                if (bytes_received <= 0) {
                    break; // 连接关闭或错误
                }
                
                buffer[bytes_received] = '\0';
                response_data += buffer;
            }

            close(sockfd);

            if (response_data.empty()) {
                response.error_message = "No response received from " + host + ":" + std::to_string(port);
                return response;
            }

            LOG_DEBUG("收到响应数据 " + std::to_string(response_data.length()) + " 字节");
            LOG_DEBUG("响应数据: " + response_data.substr(0, 500) + (response_data.length() > 500 ? "..." : ""));

            // 解析响应
            response = parseHttpResponse(response_data);

            // 只有在状态码表示成功时才设置success为true
            // HTTP状态码2xx表示成功
            if (response.status_code >= 200 && response.status_code < 300) {
                response.success = true;
            } else {
                response.success = false;
                if (response.error_message.empty()) {
                    response.error_message = "HTTP error: " + std::to_string(response.status_code);
                }
            }

        } catch (const std::exception& e) {
            response.error_message = "Exception: " + std::string(e.what());
        }

        return response;
    }

    bool HttpClient::parseUrl(const std::string& url, std::string& host, int& port, std::string& path) {
        // 简单的URL解析，支持 http://host:port/path 格式
        std::regex url_regex(R"(^https?://([^:/]+)(?::(\d+))?(/.*)?$)");
        std::smatch matches;
        
        if (std::regex_match(url, matches, url_regex)) {
            host = matches[1].str();
            port = matches[2].matched ? std::stoi(matches[2].str()) : 80;
            path = matches[3].matched ? matches[3].str() : "/";
            return true;
        }
        
        return false;
    }

    std::string HttpClient::buildHttpRequest(const std::string& method,
                                           const std::string& path,
                                           const std::string& host,
                                           const std::string& body,
                                           const std::unordered_map<std::string, std::string>& headers) {
        std::ostringstream request;
        
        // 请求行
        request << method << " " << path << " HTTP/1.1\r\n";
        
        // Host头
        request << "Host: " << host << "\r\n";
        
        // 默认头部
        for (const auto& [key, value] : default_headers_) {
            request << key << ": " << value << "\r\n";
        }
        
        // 自定义头部
        for (const auto& [key, value] : headers) {
            request << key << ": " << value << "\r\n";
        }
        
        // Content-Length
        if (!body.empty()) {
            request << "Content-Length: " << body.length() << "\r\n";
        }
        
        // 空行
        request << "\r\n";
        
        // 请求体
        if (!body.empty()) {
            request << body;
        }
        
        return request.str();
    }

    HttpClientResponse HttpClient::parseHttpResponse(const std::string& response_data) {
        HttpClientResponse response;
        
        // 查找头部和体的分隔符
        size_t header_end = response_data.find("\r\n\r\n");
        if (header_end == std::string::npos) {
            response.error_message = "Invalid HTTP response format";
            return response;
        }
        
        std::string header_part = response_data.substr(0, header_end);
        response.body = response_data.substr(header_end + 4);
        
        // 解析状态行
        std::istringstream header_stream(header_part);
        std::string status_line;
        std::getline(header_stream, status_line);
        
        // 提取状态码
        std::regex status_regex(R"(HTTP/\d\.\d (\d+))");
        std::smatch status_matches;
        if (std::regex_search(status_line, status_matches, status_regex)) {
            response.status_code = std::stoi(status_matches[1].str());
        }
        
        // 解析头部
        std::string header_line;
        while (std::getline(header_stream, header_line) && !header_line.empty()) {
            // 移除回车符
            if (!header_line.empty() && header_line.back() == '\r') {
                header_line.pop_back();
            }
            
            size_t colon_pos = header_line.find(':');
            if (colon_pos != std::string::npos) {
                std::string key = header_line.substr(0, colon_pos);
                std::string value = header_line.substr(colon_pos + 1);
                
                // 去除前后空格
                key.erase(0, key.find_first_not_of(" \t"));
                key.erase(key.find_last_not_of(" \t") + 1);
                value.erase(0, value.find_first_not_of(" \t"));
                value.erase(value.find_last_not_of(" \t") + 1);
                
                response.headers[key] = value;
            }
        }
        
        return response;
    }

} // namespace http
} // namespace common
